package com.atguigu.tingshu.album.service.impl;


import com.atguigu.tingshu.album.config.VodConstantProperties;
import com.atguigu.tingshu.album.mapper.AlbumInfoMapper;
import com.atguigu.tingshu.album.mapper.TrackInfoMapper;
import com.atguigu.tingshu.album.mapper.TrackStatMapper;
import com.atguigu.tingshu.album.service.AlbumInfoService;
import com.atguigu.tingshu.album.service.TrackInfoService;
import com.atguigu.tingshu.album.service.VodService;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.execption.GuiguException;
import com.atguigu.tingshu.common.result.Result;
import com.atguigu.tingshu.common.result.ResultCodeEnum;
import com.atguigu.tingshu.common.util.UploadFileUtil;
import com.atguigu.tingshu.model.album.AlbumInfo;
import com.atguigu.tingshu.model.album.TrackInfo;
import com.atguigu.tingshu.model.album.TrackStat;
import com.atguigu.tingshu.query.album.TrackInfoQuery;
import com.atguigu.tingshu.user.client.UserInfoFeignClient;
import com.atguigu.tingshu.vo.album.*;
import com.atguigu.tingshu.vo.user.UserInfoVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qcloud.vod.VodUploadClient;
import com.qcloud.vod.model.VodUploadRequest;
import com.qcloud.vod.model.VodUploadResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
@SuppressWarnings({"all"})
public class TrackInfoServiceImpl extends ServiceImpl<TrackInfoMapper, TrackInfo> implements TrackInfoService {

    @Autowired
    private TrackInfoMapper trackInfoMapper;

    // 腾讯云
    @Autowired
    private VodConstantProperties vodConstantProperties;

    @Autowired
    private VodService vodService;

    @Autowired
    private TrackStatMapper trackStatMapper;

    @Autowired
    private AlbumInfoMapper albumInfoMapper;


    @Autowired
    private AlbumInfoService albumInfoService;


    @Autowired
    private UserInfoFeignClient userInfoFeignClient;


    /**
     * 更新声音播放量
     * @param trackId
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updateTrackStat(TrackStatMqVo trackStatMqVo) {
        this.trackInfoMapper.updateTrackStat(trackStatMqVo.getTrackId(),trackStatMqVo.getCount(),trackStatMqVo.getStatType());

        if(trackStatMqVo.getStatType().equals(SystemConstant.TRACK_STAT_PLAY)){
            this.albumInfoMapper.updateAlbumStat(trackStatMqVo.getAlbumId(),trackStatMqVo.getCount(),trackStatMqVo.getStatType());
        }
    }

    @Override
    public TrackInfo getTrackInfo(Long trackId) {
        System.out.println("trackId = " + trackId);
//        TrackInfo trackInfo = trackInfoMapper.selectById(trackId);
        TrackInfo trackInfo = this.getById(trackId);
        System.out.println("trackId = " + trackId);
        return trackInfo;
    }

    /**
     * 分页查询声音列表
     *
     * @param albumTrackListVoPage
     * @param albumId
     * @return
     */
    @Override
    public IPage<AlbumTrackListVo> findAlbumTrackPage(Page<AlbumTrackListVo> albumTrackListVoPage, Long albumId, Long userId) {

//        //根据专辑Id查询声音列表(拿到了声音列表)
//        IPage<AlbumTrackListVo> albumTrackListVo = trackInfoMapper.selectAlbumTrackList(albumTrackListVoPage, albumId);
//        //获取专辑信息
//        AlbumInfo albumInfo = albumInfoMapper.selectById(albumId);
//        //判断当前用户是否为登录
//        if (null == userId) {//用户没有登录的状态
//            //专辑的类型3种，除了0101都是付费的,且都需要付费显示
//            if (!SystemConstant.ALBUM_PAY_TYPE_FREE.equals(albumInfo.getPayType())) {
//                //获取专辑下声音的列表，并且对0102、0103的进行设置付费
//                List<AlbumTrackListVo> records = albumTrackListVo.getRecords();
//                List<AlbumTrackListVo> trackList = records.stream().filter(albumTrackList -> albumTrackList.getOrderNum() > albumInfo.getTracksForFree()).collect(Collectors.toList());
//                if (!CollectionUtils.isEmpty(trackList)) {
//                    for (AlbumTrackListVo trackListVo : trackList) {
//                        trackListVo.setIsShowPaidMark(true);
//                    }
//                }
//            }
//            //////todo
//            return albumTrackListVo;
//        } else {
//            //todo vip情况
//            //设置付费标识
//            //默认不需要付费
//            boolean isNeedPay = false;
//            //当前用户登录状态
//            //查看用户的付费类型
//            if (SystemConstant.ALBUM_PAY_TYPE_VIPFREE.equals(albumInfo.getPayType())) {
//                //根据用户id获取到用户的信息
//                Result<UserInfoVo> userInfoVoResult = userInfoFeignClient.getUserInfoVoByUserId(userId);
//                UserInfoVo userInfoVo = userInfoVoResult.getData();
//
//                /*//不是vip
//                if (userInfoVo.getIsVip() == 0) {
//                    isNeedPay = true;
//                }
//                //是vip且vip过期
//                if (userInfoVo.getIsVip() == 1 && userInfoVo.getVipExpireTime().before(new Date())) {
//                    isNeedPay = true;
//                }*/
//                //
//                if (userInfoVo.getIsVip() == 0 || (userInfoVo.getIsVip() == 1 && userInfoVo.getVipExpireTime().before(new Date()))) {
//                    isNeedPay = true;
//                }
//
//            } else if (SystemConstant.ALBUM_PAY_TYPE_REQUIRE.equals(albumInfo.getPayType())) {
//                //todo 付费类型
//                isNeedPay = true;
//            }
//            // todo 对付费进行判断
//            if (isNeedPay) {
//                //获取需要付费的声音的列表()
//                List<AlbumTrackListVo> records = albumTrackListVo.getRecords();
//                //获取到需要付费声音的列表
//                List<AlbumTrackListVo> trackNeedPayList = records.stream().filter(albumTrackList -> albumTrackList.getOrderNum() > albumInfo.getTracksForFree()).collect(Collectors.toList());
//
//                if (!CollectionUtils.isEmpty(trackNeedPayList)) {
//
//                    //获取付费声音id列表，用于和用户购买的专辑声音进行对比
//                    List<Long> NeedPayIdList = trackNeedPayList.stream().map(AlbumTrackListVo::getTrackId).collect(Collectors.toList());
//                    //根据专辑id获取用户购买了的专辑
//                    //	获取用户购买的声音列表
//                    Result<Map<Long, Integer>> mapResult = userInfoFeignClient.getPaiedTrack(albumId,NeedPayIdList);
//                    Assert.notNull(mapResult,"声音集合不能为空.");
//                    Map<Long, Integer> map = mapResult.getData();
//                    Assert.notNull(map,"map集合不能为空.");
//                    trackNeedPayList.forEach(albumTrackList -> {
//                        //	如果map.get(albumTrackListVo.getTrackId()) == 1 已经购买过，则不显示付费标识;
//                        boolean isBuy = map.get(albumTrackList.getTrackId()) == 1 ? false : true;
//                        albumTrackList.setIsShowPaidMark(isBuy);
//                    });
//                }
//            }
//        }
//        return albumTrackListVo;
        //	根据专辑Id 获取到声音集合
        IPage<AlbumTrackListVo> pageInfo = trackInfoMapper.selectAlbumTrackList(albumTrackListVoPage,albumId);

        //	判断用户是否需要付费：0101-免费 0102-vip付费 0103-付费
        AlbumInfo albumInfo = albumInfoService.getById(albumId);
        Assert.notNull(albumInfo,"专辑对象不能为空");
        //	判断用户是否登录
        if (null == userId){
            //	除免费的专辑都需要显示付费表示
            if (!SystemConstant.ALBUM_PAY_TYPE_FREE.equals(albumInfo.getPayType())){
                //	处理试听声音，获取需要付费的声音列表
                List<AlbumTrackListVo> albumTrackNeedPaidListVoList = pageInfo.getRecords().stream().filter(albumTrackListVo -> albumTrackListVo.getOrderNum().intValue() > albumInfo.getTracksForFree()).collect(Collectors.toList());
                if (!CollectionUtils.isEmpty(albumTrackNeedPaidListVoList)){
                    albumTrackNeedPaidListVoList.forEach(albumTrackListVo -> {
                        //	显示付费通知
                        albumTrackListVo.setIsShowPaidMark(true);
                    });
                }
            }
        } else {
            //	用户已登录
            //	声明变量是否需要付费，默认不需要付费
            boolean isNeedPaid = false;
            //  vip 付费情况
            if (SystemConstant.ALBUM_PAY_TYPE_VIPFREE.equals(albumInfo.getPayType())){
                //	获取用户信息
                Result<UserInfoVo> userInfoVoResult = userInfoFeignClient.getUserInfoVoByUserId(userId);
                Assert.notNull(userInfoVoResult,"用户信息不能为空");
                UserInfoVo userInfoVo = userInfoVoResult.getData();
                //	1.	VIP 免费,如果不是vip则需要付费，将这个变量设置为true，需要购买
                if (userInfoVo.getIsVip().intValue() == 0){
                    isNeedPaid = true;
                }
                //1.1 如果是vip但是vip过期了（定时任务还为更新状态）
                if(userInfoVo.getIsVip().intValue() == 1 && userInfoVo.getVipExpireTime().before(new Date())) {
                    isNeedPaid = true;
                }
            } else if(SystemConstant.ALBUM_PAY_TYPE_REQUIRE.equals(albumInfo.getPayType())){
                //	2.	付费
                isNeedPaid = true;
            }
            //需要付费，判断用户是否购买过专辑或声音
            if(isNeedPaid) {
                //	处理试听声音，获取需要付费的声音列表
                List<AlbumTrackListVo> albumTrackNeedPaidListVoList = pageInfo.getRecords().stream().filter(albumTrackListVo -> albumTrackListVo.getOrderNum().intValue() > albumInfo.getTracksForFree()).collect(Collectors.toList());
                //	判断
                if (!CollectionUtils.isEmpty(albumTrackNeedPaidListVoList)){
                    //	判断用户是否购买该声音
                    //	获取到声音Id 集合列表
                    List<Long> trackIdList = albumTrackNeedPaidListVoList.stream().map(AlbumTrackListVo::getTrackId).collect(Collectors.toList());
                    //	获取用户购买的声音列表
                    Result<Map<Long, Integer>> mapResult = userInfoFeignClient.getPaiedTrack(albumId,trackIdList);
                    Assert.notNull(mapResult,"声音集合不能为空.");
                    Map<Long, Integer> map = mapResult.getData();
                    Assert.notNull(map,"map集合不能为空.");
                    albumTrackNeedPaidListVoList.forEach(albumTrackListVo -> {
                        //	如果map.get(albumTrackListVo.getTrackId()) == 1 已经购买过，则不显示付费标识;
                        boolean isBuy = map.get(albumTrackListVo.getTrackId()) == 1 ? false : true;
                        albumTrackListVo.setIsShowPaidMark(isBuy);
                    });
                }
            }
        }
        // 返回集合数据
        return pageInfo;
    }

    /**
     * 保存修改的声音
     *
     * @param trackId
     * @param trackInfoVo
     */
    @Override
    public void updateTrackInfo(Long trackId, TrackInfoVo trackInfoVo) {
        //1.获取声音对象
        TrackInfo trackInfo = this.getById(trackId);
        //3.获取到原来的媒体文件
        String oldMediaFileId = trackInfo.getMediaFileId();
        //2.属性拷贝
        BeanUtils.copyProperties(trackInfoVo, trackInfo);
        //4.获取到新保存的媒体文件
        String newMediaFileId = trackInfoVo.getMediaFileId();
        //5.判断两次是不是一样的。如果不是一样的说明媒体文件也进行了修改，就把原来的媒体文件也进行删除
        if (!oldMediaFileId.equals(newMediaFileId)) {
            //说明更换了媒体文件
            TrackMediaInfoVo mediaInfo = vodService.getMediaInfo(newMediaFileId);
            if (mediaInfo == null) {
                //空，抛出异常
                throw new GuiguException(ResultCodeEnum.VOD_FILE_ID_ERROR);
            }
            //不为空，设置属性
            trackInfo.setMediaDuration(mediaInfo.getDuration());
            trackInfo.setMediaUrl(mediaInfo.getMediaUrl());
            trackInfo.setMediaType(mediaInfo.getType());
            trackInfo.setMediaSize(mediaInfo.getSize());
            //就删除原有的媒体文件
            this.vodService.removeTrack(oldMediaFileId);
        }
    }

    /**
     * 删除声音
     *
     * @param trackId
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void removeTrackInfo(Long trackId) {
        /*//根据trackId获取trackInfo对象
        TrackInfo trackInfo = trackInfoMapper.selectById(trackId);
        //删除track
        trackInfoMapper.deleteById(trackInfo);
        //删除统计数据
        trackStatMapper.delete(new LambdaQueryWrapper<TrackStat>().eq(TrackStat::getTrackId,trackId));
        //删除专辑下的声音，首先获取到albumInfo对象
        AlbumInfo albumInfo = albumInfoService.getAlbumInfoById(trackInfo.getAlbumId());
        albumInfo.setIncludeTrackCount(albumInfo.getIncludeTrackCount()-1);

        //更新专辑数量
        albumInfoMapper.updateById(albumInfo);

        //更新顺序(根据专辑Id)
        trackInfoMapper.updateTrackNum(trackInfo.getOrderNum(),albumInfo.getId());

        //调用远程云点播,进行删除
        vodService.removeTrack(trackInfo.getMediaFileId());*/

        //  先获取到专辑对象;
        TrackInfo trackInfo = trackInfoMapper.selectById(trackId);
        //  track_info is_deleted = 1;
        trackInfoMapper.deleteById(trackId);
        //  track_stat is_deleted = 1;
        trackStatMapper.delete(new LambdaQueryWrapper<TrackStat>().eq(TrackStat::getTrackId, trackId));
        //  album_info.include_track_count-1;
        AlbumInfo albumInfo = albumInfoService.getAlbumInfoById(trackInfo.getAlbumId());
        //  修改包含声音总数
        albumInfo.setIncludeTrackCount(albumInfo.getIncludeTrackCount() - 1);
        //  更新专辑最新数据
        this.albumInfoMapper.updateById(albumInfo);
        //  声音对应的order_num 应该-1;
        //  update track_info set order_num = order_num - 1 where order_num > 51 and album_id = 1 and is_deleted = 0;
        trackInfoMapper.updateTrackNum(trackInfo.getOrderNum(), albumInfo.getId());
        //  删除云点播中的数据:
        vodService.removeTrack(trackInfo.getMediaFileId());


    }

    /**
     * 分页查询用户声音
     *
     * @param page
     * @param trackInfoQuery
     * @return
     */
    @Override
    public IPage<TrackListVo> findUserTrackPage(Page<TrackListVo> page, TrackInfoQuery trackInfoQuery) {
        return trackInfoMapper.selectTrackPage(page, trackInfoQuery);
    }

    /**
     * 保存声音
     *
     * @param trackMediaInfoVo
     * @param userId
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void saveTrackInfo(TrackInfoVo trackInfoVo, Long userId) {
        //todo 分析传来的数据都来自哪几张表
        //创建声音对象
        TrackInfo trackInfo = new TrackInfo();
        //将前端传进来的属性拷贝到trackInfo对象中
        BeanUtils.copyProperties(trackInfoVo, trackInfo);
        //但是我们还要看前端没有给我们传递什么属性,我们给属性加进去
        //设置用户Id
        trackInfo.setUserId(userId);
        trackInfo.setAlbumId(trackInfoVo.getAlbumId());
        //order_num声音的序号
        AlbumInfo albumInfo = albumInfoMapper.selectById(trackInfoVo.getAlbumId());
        //为我专辑下面的声音进行序号加1 (新加进来一个，那么我的声音肯定要序号+1)
        trackInfo.setOrderNum(albumInfo.getIncludeTrackCount() + 1);
        //获取媒体源
        TrackMediaInfoVo mediaInfoVo = vodService.getMediaInfo(trackInfoVo.getMediaFileId());
        //为媒体文件设置媒体时间
        trackInfo.setMediaDuration(mediaInfoVo.getDuration());

        trackInfo.setMediaSize(mediaInfoVo.getSize());

        trackInfo.setMediaType(mediaInfoVo.getType());
        //保存数据
        trackInfoMapper.insert(trackInfo);

        //todo 保存stat统计表
        this.saveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_PLAY);
        this.saveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_COLLECT);
        this.saveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_PRAISE);
        this.saveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_COMMENT);

        //todo 更新专辑对应的声音总数;
        albumInfo.setIncludeTrackCount(albumInfo.getIncludeTrackCount() + 1);
        this.albumInfoMapper.updateById(albumInfo);
    }

    public void saveTrackStat(Long trackId, String statPlay) {
        //  创建声音统计对象
        TrackStat trackStat = new TrackStat();
        //  赋值：
        trackStat.setTrackId(trackId);
        trackStat.setStatType(statPlay);
        trackStat.setStatNum(new Random().nextInt(1000));
        this.trackStatMapper.insert(trackStat);
    }

    @Override
    public HashMap<String, Object> uploadTrack(MultipartFile file) {
        // 创建上传对象
        VodUploadClient client = new VodUploadClient(vodConstantProperties.getSecretId(), vodConstantProperties.getSecretKey());
        // 设置上传参数(请求对象)
        VodUploadRequest request = new VodUploadRequest();
        String tempPath = UploadFileUtil.uploadTempPath(vodConstantProperties.getTempPath(), file);

        request.setMediaFilePath(tempPath);

        try {
            // 设置上传参数(响应对象)
            VodUploadResponse response = client.upload(vodConstantProperties.getRegion(), request);
            log.info("Upload FileId = {}", response.getFileId());
            //设置一个hashMap,存储流文件媒体的id和key
            HashMap<String, Object> map = new HashMap<>();
            map.put("mediaFileId", response.getFileId());
            map.put("mediaUrl", response.getMediaUrl());
            return map;
        } catch (Exception e) {
            // 业务方进行异常处理
            log.error("Upload Err", e);
        }
        return null;
    }
}
